package hotel.callback.oversea.task;

import hotel.callback.oversea.config.AsynHttpClientFactory;
import hotel.callback.oversea.config.service.RedisService;
import hotel.callback.oversea.utils.MtUtils;
import hotel.base.oversea.constant.MeituanConstants;
import hotel.base.oversea.constant.enums.MtGoodsEnums;
import hotel.base.oversea.constant.enums.MtHotelEnums;
import hotel.base.oversea.utils.DateUtil;
import hotel.base.oversea.utils.GsonUtils;
import hotel.base.oversea.utils.Result;
import hotel.callback.oversea.vo.meituan.CommonParamsVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;


@Slf4j
@Component
public class MeituanPartTimeQueryStatusVSecTask {
    private String timestamp = "mcohgdt"+String.valueOf(System.currentTimeMillis());
    @Autowired
    private RedisService redisService;
    private void setTimestamp(String timestamp){
        this.timestamp = timestamp;
    }
    @Async("threadPoolSt")
    public Result<Object> executeQueryHotelGoodsStatus(List<String> popList, Integer daysCommon){
        //log.info("MeituanPartTimeQueryStatusTask {} >>>>>>>>> 异步线程 节点定时器查询房态task  开始执行时间：daysCommon={},popList={}",timestamp,daysCommon,GsonUtils.GsonString(popList));
        final HttpPost[] requests = buildRequestData(popList,daysCommon);
        CloseableHttpAsyncClient httpClient = AsynHttpClientFactory.getCloseableHttpAsyncClient();
        //发起多线程异步请求
        final CountDownLatch latch = new CountDownLatch(requests.length);
        for(final HttpPost request: requests){
            if(ObjectUtils.isEmpty(request)){
                continue;
            }
            httpClient.execute(request, new FutureCallback<HttpResponse>(){
                //处理内部业务
                String hotelInfos = request.getHeaders("hhb")[0].getValue();
                String hotelId = hotelInfos.split("_")[0];
                String start = hotelInfos.split("_")[1];
                String end = hotelInfos.split("_")[2];
                @Override
                public void completed(final HttpResponse response) {
                    latch.countDown();
                    //log.info(" [completed] "+request.getURI() + "->",response.getStatusLine());
                    //log.info(" [completed] 完成 request-head={}",hotelInfos);
                    try {
                        String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                        if(!ObjectUtils.isEmpty(content) && content.contains("限流")){
                            log.info("异步请求成功hotelId={},content={},i={}",hotelId,content,request.getHeaders("i"));
                        }else{
                            log.info("异步请求成功hotelId={}",hotelId);
                        }
                        //push到队列，等待解析定时器解析是否有发生变化的房态（优势酒店）
                        redisService.lPush(MeituanConstants.REIDS_MT_API_STATUS_DATA_QUEUE,content+"_hhb"+hotelId+"_hhb"+start+"_hhb"+end);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                @Override
                public void failed(Exception excptn) {
                    latch.countDown();
                    log.info(request.getURI() + "->" + excptn);
                    log.info(request.getURI() + "failed异步请求房态接口返回失败hotelId=" + hotelId);
                }
                @Override
                public void cancelled() {
                    latch.countDown();
                    log.info(request.getURI() + "cancelled");
                    log.info(request.getURI() + "cancelled异步请求房态接口返回异常hotelId=" + hotelId);
                }
            });
        }
        log.info("MeituanPartTimeQueryStatusTask {} >>>>>>>>> 异步线程 节点定时器查询房态task  执行结束时间：{}",timestamp, DateUtil.getNowTime());
        return new Result<>();
    }

    private final HttpPost[] buildRequestData(List<String> popList, Integer daysCommon) {
        String url = MeituanConstants.URL;
        String version = MeituanConstants.VERSION;//版本号
        int partnerId = MeituanConstants.BUSINESS_ID;//平台分配给第三方渠道的分销业务ID
        String accesskey = MeituanConstants.ACCESS_KEY;//平台分配给第三方渠道的安全凭证公钥
        String method = MtHotelEnums.apiMethodEnum.METHOD_HOTEL_GOODS_STATUS.getMethod();

        //log.info("buildRequestData popList={}", GsonUtils.GsonString(popList));
        Date nowDate = new Date();
        String endDate = DateUtil.formatDate(DateUtil.addDay(nowDate,daysCommon),"yyyy-MM-dd");
        if(null != redisService.get("query_status_time_days_endDate")){
            endDate = (String)redisService.get("query_status_time_days_endDate");
        }

        //调用美团房态接口，日历房态接口,默认全日房 （根据时间段数据返回）
        //version  2020-08-26 2:21  mf   DateUtil.getFontsDay 提前一天的房态价格也要更新 用户凌晨可以买前一天至今天中午的房间
        String startDateRoomStatus = DateUtil.formatDate(nowDate,"yyyy-MM-dd");
        String nowStr = DateUtil.formatDate(nowDate,"yyyy-MM-dd HH");
        if(Integer.valueOf(nowStr.split(" ")[1])<6){
            startDateRoomStatus = DateUtil.getFontsDay(startDateRoomStatus);
        }

        //log.info("executeQueryHotelGoodsStatus popListSize={},popList={}",popList==null?0:popList.size(),GsonUtils.GsonString(popList));
        if(ObjectUtils.isEmpty(popList)){
            return null;
        }

        //构建requests
        //final HttpPost[] requests = new HttpPost[countTask.intValue()];
        final HttpPost[] requests = new HttpPost[popList.size()];
        for (int i = 0; i < requests.length; i++) {
            String hotelId = popList.get(i);
            if(ObjectUtils.isEmpty(hotelId)){
                log.info("[request]getRpApiFutureCallback 队列已无数据");
                break;
            }

            //构建请求参数,提交请求
            String data = "";
            Map<String,Object> dataMap = new HashMap<>();
            dataMap.put("hotelId",hotelId);
            dataMap.put("checkinDate",startDateRoomStatus);
            dataMap.put("checkoutDate",endDate);
            dataMap.put("goodsType", MtGoodsEnums.roomDateTypeEnum.DAY.getCode());
            data = GsonUtils.GsonString(dataMap);
            long  timestamp=System.currentTimeMillis()/1000;//10位时间戳
            int nonce= new Random().nextInt(Integer.MAX_VALUE);//随机正整数。与timestamp联合使用以防止重放攻击
            CommonParamsVo commonParamsVo = new CommonParamsVo();
            commonParamsVo.setMethod(method).setVersion(version).setTimestamp(timestamp).setNonce(nonce).setPartnerId(partnerId).setAccesskey(accesskey).setData(data);
            String signature= MtUtils.createsSignature(commonParamsVo);
            commonParamsVo.setSignature(signature);

            HttpPost httpPostRequest = new HttpPost(url);
            //log.info("getRpApiFutureCallback 请求参数 hotelId={},commonParamsVo={}",hotelId,GsonUtils.GsonString(commonParamsVo));
            StringEntity postEntity = new StringEntity(GsonUtils.GsonString(commonParamsVo), "UTF-8");
            httpPostRequest.addHeader("Content-Type", "application/json");
            httpPostRequest.setEntity(postEntity);
            httpPostRequest.setHeader("hhb", hotelId+"_"+startDateRoomStatus+"_"+endDate);
            requests[i] = httpPostRequest;
        }
        log.info("buildRequestData 返回 requestssize={}",requests.length);
        return requests;
    }



}
